﻿using System;

namespace Babylon.Animations
{
    public abstract class AnimationBase : IAnimation
    {
        private float _startTime;
        private float _pausedDuration;
        private float _currentTime;

        public float StartTime { get { return _startTime; } }
        public float PausedDuration { get { return _pausedDuration; } }
        public float CurrentTime { get { return _currentTime; } }

        public float AnimationEllapsedTime
        {
            get
            {
                switch (AnimationState)
                {
                    case AnimationState.Stopped:
                        return 0;
                    default:
                        return CurrentTime - StartTime - PausedDuration;
                }
            }
        }

        protected AnimationBase()
        {
            AnimationState = AnimationState.Stopped;
        }

        protected virtual void OnStarted()
        {

        }

        protected virtual void OnPaused()
        {
        }

        protected virtual void OnResumed()
        {
            
        }

        protected virtual void OnStopped()
        {
            
        }

        protected virtual void OnUpdated()
        {
            
        }

        public AnimationState AnimationState { get; private set; }

        public void Start(float currentTime)
        {
            if(AnimationState != AnimationState.Stopped)
                throw new InvalidOperationException("Animation is not stopped");
            _startTime = currentTime;
            _currentTime = currentTime;
            _pausedDuration = 0;
            AnimationState = AnimationState.Running;
            OnStarted();
        }

        public void Pause(float currentTime)
        {
            if(AnimationState!= AnimationState.Running)
                throw new InvalidOperationException("Animation is not running");
            _currentTime = currentTime;
            AnimationState = AnimationState.Paused;
            OnPaused();
        }

        public void Resume(float currentTime)
        {
            if (AnimationState != AnimationState.Paused)
                throw new InvalidOperationException("Animation is not paused");
            _pausedDuration += currentTime - _currentTime;
            _currentTime = currentTime;
            AnimationState = AnimationState.Running;
            OnResumed();
        }

        public void Stop(float currentTime)
        {
            if(AnimationState == AnimationState.Stopped)
                throw new InvalidOperationException("Animation is already stopped");
            AnimationState = AnimationState.Stopped;
            _currentTime = currentTime;
            _startTime = 0;
            _pausedDuration = 0;
            OnStopped();
        }

        public void Update(float currentTime)
        {
            if (AnimationState == AnimationState.Paused)
                _pausedDuration += currentTime - _currentTime;
            _currentTime = currentTime;
            OnUpdated();
        }

        public bool RepeatForever { get; set; }

        public bool AutoReverse { get; set; }
    }
}
